package com.zenithmind.chat.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.chat.mapper.ChatGroupMemberMapper;
import com.zenithmind.chat.mapper.ChatMessageMapper;
import com.zenithmind.chat.mapper.ChatMessageReadMapper;
import com.zenithmind.chat.pojo.entity.ChatGroupMember;
import com.zenithmind.chat.pojo.entity.ChatMessage;
import com.zenithmind.chat.pojo.entity.ChatMessageRead;
import com.zenithmind.chat.pojo.vo.ChatUserVO;
import com.zenithmind.chat.service.ChatMessageReadService;
import com.zenithmind.common.context.UserContext;
import com.zenithmind.common.exception.BusinessException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 消息已读记录服务实现类
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ChatMessageReadServiceImpl extends ServiceImpl<ChatMessageReadMapper, ChatMessageRead> 
        implements ChatMessageReadService {

    private final ChatMessageMapper messageMapper;
    private final ChatGroupMemberMapper groupMemberMapper;

    @Override
    public List<ChatUserVO> getMessageReadUsers(String messageId) {
        LambdaQueryWrapper<ChatMessageRead> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessageRead::getMessageId, messageId)
               .orderByDesc(ChatMessageRead::getReadTime);
        
        List<ChatMessageRead> readRecords = list(wrapper);
        
        return readRecords.stream()
            .map(this::convertToUserVO)
            .collect(Collectors.toList());
    }

    @Override
    public List<ChatUserVO> getMessageUnreadUsers(String messageId, String groupId) {
        // 获取消息信息
        ChatMessage message = messageMapper.selectById(messageId);
        if (message == null) {
            throw new BusinessException("消息不存在");
        }
        
        // 获取群组所有成员
        LambdaQueryWrapper<ChatGroupMember> memberWrapper = new LambdaQueryWrapper<>();
        memberWrapper.eq(ChatGroupMember::getGroupId, groupId)
                    .eq(ChatGroupMember::getStatus, 1)
                    .eq(ChatGroupMember::getIsDeleted, 0);
        
        List<ChatGroupMember> allMembers = groupMemberMapper.selectList(memberWrapper);
        
        // 获取已读用户ID列表
        LambdaQueryWrapper<ChatMessageRead> readWrapper = new LambdaQueryWrapper<>();
        readWrapper.eq(ChatMessageRead::getMessageId, messageId);
        
        List<String> readUserIds = list(readWrapper).stream()
            .map(ChatMessageRead::getUserId)
            .collect(Collectors.toList());
        
        // 过滤出未读用户
        return allMembers.stream()
            .filter(member -> !readUserIds.contains(member.getUserId()))
            .filter(member -> !member.getUserId().equals(message.getSenderId())) // 排除发送者
            .map(this::convertMemberToUserVO)
            .collect(Collectors.toList());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean markMessageAsRead(String messageId, String userId) {
        // 检查是否已读
        if (checkUserReadMessage(messageId, userId)) {
            return true; // 已读，直接返回
        }   
        
        ChatMessageRead readRecord = new ChatMessageRead();
        readRecord.setMessageId(messageId);
        readRecord.setUserId(userId);
        readRecord.setUserName(UserContext.getUsername());  
        readRecord.setReadTime(LocalDateTime.now());
        
        boolean result = save(readRecord);
        
        if (result) {
            log.info("用户 {} 标记消息 {} 为已读", userId, messageId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean batchMarkAsRead(List<String> messageIds, String userId) {
        if (CollectionUtils.isEmpty(messageIds)) {
            return false;
        }
        
        List<ChatMessageRead> readRecords = new ArrayList<>();
        LocalDateTime readTime = LocalDateTime.now();
        String userName = UserContext.getUsername();
        
        for (String messageId : messageIds) {
            if (!checkUserReadMessage(messageId, userId)) {
                ChatMessageRead readRecord = new ChatMessageRead();
                readRecord.setMessageId(messageId);
                readRecord.setUserId(userId);
                readRecord.setUserName(userName);
                readRecord.setReadTime(readTime);
                
                readRecords.add(readRecord);
            }
        }
        
        if (!CollectionUtils.isEmpty(readRecords)) {
            boolean result = saveBatch(readRecords);
            log.info("用户 {} 批量标记 {} 条消息为已读", userId, readRecords.size());
            return result;
        }
        
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean markGroupMessagesAsRead(String groupId, String userId) {
        // 获取用户在群组中未读的消息
        LambdaQueryWrapper<ChatMessage> messageWrapper = new LambdaQueryWrapper<>();
        messageWrapper.eq(ChatMessage::getGroupId, groupId)
                     .ne(ChatMessage::getSenderId, userId) // 排除自己发送的消息
                     .eq(ChatMessage::getStatus, 1)
                     .eq(ChatMessage::getIsDeleted, 0);
        
        List<ChatMessage> messages = messageMapper.selectList(messageWrapper);
        
        if (CollectionUtils.isEmpty(messages)) {
            return true;
        }
        
        // 过滤出未读消息
        List<String> unreadMessageIds = new ArrayList<>();
        for (ChatMessage message : messages) {
            if (!checkUserReadMessage(message.getId(), userId)) {
                unreadMessageIds.add(message.getId());
            }
        }
        
        if (!CollectionUtils.isEmpty(unreadMessageIds)) {
            return batchMarkAsRead(unreadMessageIds, userId);
        }
        
        return true;
    }

    @Override
    public Boolean checkUserReadMessage(String messageId, String userId) {
        LambdaQueryWrapper<ChatMessageRead> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessageRead::getMessageId, messageId)
               .eq(ChatMessageRead::getUserId, userId);
        
        return count(wrapper) > 0;
    }

    @Override
    public LocalDateTime getUserLastReadTime(String groupId, String userId) {
        // 查询用户在该群组中最后一次已读消息的时间
        LambdaQueryWrapper<ChatMessageRead> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessageRead::getUserId, userId)
               .orderByDesc(ChatMessageRead::getReadTime)
               .last("LIMIT 1");
        
        // 需要关联消息表来过滤群组
        // 这里简化处理，实际应该使用JOIN查询
        ChatMessageRead lastRead = getOne(wrapper);
        
        return lastRead != null ? lastRead.getReadTime() : null;
    }

    @Override
    public Integer countMessageReadUsers(String messageId) {
        LambdaQueryWrapper<ChatMessageRead> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatMessageRead::getMessageId, messageId);
        
        return Math.toIntExact(count(wrapper));
    }

    @Override
    public Integer countUserUnreadMessages(String groupId, String userId) {
        // 获取群组所有消息（排除用户自己发送的）
        LambdaQueryWrapper<ChatMessage> messageWrapper = new LambdaQueryWrapper<>();
        messageWrapper.eq(ChatMessage::getGroupId, groupId)
                     .ne(ChatMessage::getSenderId, userId)
                     .eq(ChatMessage::getStatus, 1)
                     .eq(ChatMessage::getIsDeleted, 0);
        
        List<ChatMessage> messages = messageMapper.selectList(messageWrapper);
        
        if (CollectionUtils.isEmpty(messages)) {
            return 0;
        }
        
        // 统计未读消息数量
        int unreadCount = 0;
        for (ChatMessage message : messages) {
            if (!checkUserReadMessage(message.getId(), userId)) {
                unreadCount++;
            }
        }
        
        return unreadCount;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cleanExpiredReadRecords(Integer days) {
        LocalDateTime expireTime = LocalDateTime.now().minusDays(days);
        
        LambdaQueryWrapper<ChatMessageRead> wrapper = new LambdaQueryWrapper<>();
        wrapper.lt(ChatMessageRead::getReadTime, expireTime);
        
        List<ChatMessageRead> expiredRecords = list(wrapper);
        
        if (!CollectionUtils.isEmpty(expiredRecords)) {
            remove(wrapper);
            log.info("清理 {} 条过期已读记录", expiredRecords.size());
            return expiredRecords.size();
        }
        
        return 0;
    }

    @Override
    public Object getReadStatistics(String messageId, String groupId, String startTime, String endTime) {
        LambdaQueryWrapper<ChatMessageRead> wrapper = new LambdaQueryWrapper<>();
        
        if (StringUtils.hasText(messageId)) {
            wrapper.eq(ChatMessageRead::getMessageId, messageId);
        }
        
        if (StringUtils.hasText(startTime)) {
            wrapper.ge(ChatMessageRead::getReadTime, LocalDateTime.parse(startTime));
        }
        
        if (StringUtils.hasText(endTime)) {
            wrapper.le(ChatMessageRead::getReadTime, LocalDateTime.parse(endTime));
        }
        
        long totalReads = count(wrapper);
        
        return new Object() {
            public final Long total = totalReads;
            public final Long today = 0L;
            public final Long thisWeek = 0L;
            public final Long thisMonth = 0L;
        };
    }

    /**
     * 转换为用户VO对象
     */
    private ChatUserVO convertToUserVO(ChatMessageRead readRecord) {
        ChatUserVO vo = new ChatUserVO();
        vo.setId(readRecord.getUserId());
        vo.setName(readRecord.getUserName());
        vo.setReadTime(readRecord.getReadTime());
        
        return vo;
    }

    /**
     * 转换群组成员为用户VO对象
     */
    private ChatUserVO convertMemberToUserVO(ChatGroupMember member) {
        ChatUserVO vo = new ChatUserVO();
        vo.setId(member.getUserId());
        vo.setName(member.getUserName());
        vo.setAvatar(member.getUserAvatar());
        vo.setRole(member.getRole());
        
        return vo;
    }
}
